#Region ;**** Directives created by AutoIt3Wrapper_GUI ****
#AutoIt3Wrapper_Icon=favicon.ico
#AutoIt3Wrapper_Outfile=Main.exe
#AutoIt3Wrapper_UseX64=n
#EndRegion ;**** Directives created by AutoIt3Wrapper_GUI ****
#RequireAdmin
#include <GUIConstantsEx.au3>
#include <ColorConstants.au3>
#include <StaticConstants.au3>
#include <MsgBoxConstants.au3>
#include <EditConstants.au3>
#include <WindowsConstants.au3>
#include <Constants.au3>
#include <Array.au3>
#include <StringConstants.au3>
#include <GuiListView.au3>
#include <Misc.au3>
#include <Common.au3>
#include <FileConstants.au3>
FileInstall(".\CheckService.exe", @ScriptDir & "\CheckService.exe" ,$FC_OVERWRITE )
;--------------Const
Global $CheckServiceSwitch = 1 ;
Global $StatusFlicking = False ; 记录图标是否在闪烁
Global $ServiceEnabled = False ; 记录服务是否可用
Global $CheckServicePID = 0;
;--------------Opt
Opt("GUIOnEventMode", 1) ; gui事件模型
Opt("TrayMenuMode", 1 + 2 + 8) ;禁用默认选项
Opt("TrayOnEventMode", 1) ; 启用托盘事件通知

;---------检查进程
If _Singleton("FlyfoxTesting.exe", 1) == 0 Then
	MsgBox($MB_SYSTEMMODAL + $MB_ICONWARNING, $MSGBOX_TITLE, "飞狐检测程序正在运行")
	Exit
EndIf

;=============托盘
TraySetClick(8)
;TraySetOnEvent($TRAY_EVENT_PRIMARYDOUBLE, "TrayTrigger")
TraySetOnEvent($TRAY_EVENT_PRIMARYUP, "TrayTrigger")
TraySetIcon("favicon.ico")

;Local $checkServiceTrayBtn = TrayCreateItem("检测服务")
;TrayItemSetOnEvent($checkServiceTrayBtn, "CheckService")

;~ Local $modifyPortTrayBtn = TrayCreateItem("强改端口")
;~ TrayItemSetOnEvent($modifyPortTrayBtn, "ModifyPort")

Local $checkServiceSwitchTrayBtn = TrayCreateItem("关闭自动检测服务")
TrayItemSetOnEvent($checkServiceSwitchTrayBtn, "SwitchCheckService")

Local $exitTrayBtn = TrayCreateItem("退出")
TrayItemSetOnEvent($exitTrayBtn, "TrayItemTrigger")

;===============窗口
Local $MainGui = GUICreate("飞狐环境监测程序", 500, 500)
GUISetOnEvent($GUI_EVENT_CLOSE, "GUIClose")
GUISetIcon("favicon.ico")

Local $label = GUICtrlCreateLabel("飞狐服务端口占用情况: ", 0, 5, 500, 20)

Local $ListView = GUICtrlCreateListView("    进程名    |    进程ID    |    影响端口    ", 0, 25, 500, 350)

Local $btnPosY = 380
Local $btnWidth = 70 ;
Local $btnHeight = 30
Local $offsetX = 15
Local $offsetY = 40
Local $checkPortBtn = GUICtrlCreateButton("检查端口", $offsetX, $btnPosY, $btnWidth, $btnHeight)
GUICtrlSetOnEvent($checkPortBtn, "CheckPort")
Local $repairBtn = GUICtrlCreateButton("强杀", $btnWidth + $offsetX * 2, $btnPosY, $btnWidth, $btnHeight)
GUICtrlSetOnEvent($repairBtn, "KillProcess")
;~ Local $checkServiceBtn = GUICtrlCreateButton("检测服务", ($btnWidth * 2 + $offsetX * 3), $btnPosY, $btnWidth, $btnHeight)
;~ GUICtrlSetOnEvent($checkServiceBtn, "CheckService")
Local $modifyPortBtn = GUICtrlCreateButton("强改端口", ($btnWidth * 2 + $offsetX * 3), $btnPosY, $btnWidth, $btnHeight)
GUICtrlSetOnEvent($modifyPortBtn, "ModifyPort")
Local $checkTargetPortBtn = GUICtrlCreateButton("检查指定端口", ($btnWidth * 3 + $offsetX * 4), $btnPosY, $btnWidth+30, $btnHeight)
GUICtrlSetOnEvent($checkTargetPortBtn, "CheckTargetPort")

Local $closeBtn = GUICtrlCreateButton("  退出  ", ($btnWidth * 4 + $offsetX * 5) + 30, $btnPosY, $btnWidth, $btnHeight)
GUICtrlSetOnEvent($closeBtn, "GUIClose")

Local $serviceStatusIconLabel = GUICtrlCreateLabel("状态: ", $offsetX, $btnPosY + $offsetY + 10, 40, $btnHeight)

Local $serviceStatusIconLabel = GUICtrlCreateLabel("", $offsetX + 40, $btnPosY + $offsetY + 10, 12, 12)
GUICtrlSetBkColor($serviceStatusIconLabel, $COLOR_GRAY)

Local $CheckServiceSwitchBtn = GUICtrlCreateButton("关闭自动检测服务", $offsetX + 40 + 20, $btnPosY + $offsetY, Default, $btnHeight)
GUICtrlSetOnEvent($CheckServiceSwitchBtn, "SwitchCheckService")

GUISetState(@SW_SHOW)

CheckPort()

RunCheckService()
OnAutoItExitRegister("ShutdownCheckService")

ServiceStatusWait()
;============================================================Event===========================================================

Func CheckPort()
	_GUICtrlListView_DeleteAllItems($ListView)

	;tomcat
	$tomcatPort = _GetTomcatPort()
	If $tomcatPort Then
		Local $Array = _GetProgress(_GetTomcatPort())
		_ArrayToListView($Array)
	EndIf

	; rocketmq
	$Array = _GetProgress($PORT_ROCKETMQ)
	_ArrayToListView($Array)

	; redis
	$Array = _GetProgress($PORT_REDIS)
	_ArrayToListView($Array)

	; mysql
	$Array = _GetProgress($PORT_MYSQL)
	_ArrayToListView($Array)

EndFunc   ;==>CheckPort

Func CheckTargetPort()
	Local $port = InputBox($MSGBOX_TITLE, "请输入端口号", "", "",-1,-1,Default,Default,0,$MainGui)
	If @error Then ;用户点击取消
		Return
	EndIf
	If Not StringRegExp($port, "^\d{2,5}$") Then
		MsgBox($MB_SYSTEMMODAL + $MB_ICONWARNING, $MSGBOX_TITLE, "端口格式不合法,只能为2-5位数字")
		Return
	EndIf
	_GUICtrlListView_DeleteAllItems($ListView)
	;tomcat
	Local $Array = _GetProgress($port)
	_ArrayToListView($Array)

EndFunc   ;==>CheckTargetPort

Func ModifyPort()
	Local $oldPort = _GetTomcatPort()
	If @error == 1 Then
		MsgBox($MB_SYSTEMMODAL + $MB_ICONWARNING, $MSGBOX_TITLE, "无法确定服务路径,请先安装飞狐服务端")
		Return
	ElseIf @error == 2 Then
		MsgBox($MB_SYSTEMMODAL + $MB_ICONWARNING, $MSGBOX_TITLE, "打开server.xml文件失败")
		Return
	EndIf
	;Local $SERVER_FILE_PATH = $CATALINA_HOME & "\conf\server.xml";
	;Local $SERVER_FILE_BAK_PATH = $CATALINA_HOME & "\conf\server.xml.bak";

	Local $newPort = InputBox($MSGBOX_TITLE, "请输入端口号(原端口:" & $oldPort & ")", "8080", "",-1,-1,Default,Default,0,$MainGui)
	If @error Then ;用户点击取消
		Return
	EndIf
	If Not StringRegExp($newPort, "^\d{2,5}$") Then
		MsgBox($MB_SYSTEMMODAL + $MB_ICONWARNING, $MSGBOX_TITLE, "端口格式不合法,只能为2-5位数字")
		Return
	EndIf

	Local $serverFileText = _GetTomcatConfig()
	;替换端口
	Local $temp = StringRegExpReplace($serverFileText, "port=""" & $oldPort & """\s+protocol=""HTTP/1.1""", "port=""" & $newPort & """ protocol=""HTTP/1.1""")
	;备份文件
	FileCopy($SERVER_FILE_PATH, $SERVER_FILE_BAK_PATH, $FC_OVERWRITE)
	;写文件
	Local $serverFile = FileOpen($SERVER_FILE_PATH, $FO_OVERWRITE)
	Local $result = FileWrite($serverFile, $temp)
	FileFlush($serverFile)
	FileClose($serverFile)
	If $result == 1 Then ; 修改端口成功
		MsgBox($MB_SYSTEMMODAL + $MB_ICONINFORMATION, $MSGBOX_TITLE, "修改端口成功,需要重启服务器")
	Else ; 修改端口失败还原配置文件
		FileCopy($SERVER_FILE_BAK_PATH, $SERVER_FILE_PATH, $FC_OVERWRITE)
		MsgBox($MB_SYSTEMMODAL + $MB_ICONWARNING, $MSGBOX_TITLE, "修改端口失败")
	EndIf
EndFunc   ;==>ModifyPort

Func CheckService()
	;Local $bool = _CheckService()
	If Not $CheckServiceSwitch Then
		MsgBox($MB_SYSTEMMODAL + $MB_ICONWARNING, $MSGBOX_TITLE, "请先打开自动检测服务")
		Return
	EndIf
	If $ServiceEnabled Then
		MsgBox($MB_SYSTEMMODAL + $MB_ICONINFORMATION, $MSGBOX_TITLE, "恭喜您,飞狐服务已可用")
	Else
		MsgBox($MB_SYSTEMMODAL + $MB_ICONERROR, $MSGBOX_TITLE, "服务不可用")
	EndIf
EndFunc   ;==>CheckService

Func SwitchCheckService()
	;关闭自动检测服务
	If $CheckServiceSwitch Then
		$CheckServiceSwitch = False
		CloseCheckService()
		GUICtrlSetData($CheckServiceSwitchBtn, "打开自动检测服务")
		TrayItemSetText($checkServiceSwitchTrayBtn, "打开自动检测服务")
	Else ;打开自动检测服务
		$CheckServiceSwitch = True
		OpenCheckService()
		GUICtrlSetData($CheckServiceSwitchBtn, "关闭自动检测服务")
		TrayItemSetText($checkServiceSwitchTrayBtn, "关闭自动检测服务")
	EndIf
EndFunc   ;==>SwitchCheckService

Func KillProcess()
	$selectLine = GUICtrlRead(GUICtrlRead($ListView))
	If Not $selectLine Then
		MsgBox($MB_SYSTEMMODAL + $MB_ICONWARNING, $MSGBOX_TITLE, "请选中要强杀的进程")
		Return
	EndIf
	$Array = StringSplit($selectLine, "|", $STR_NOCOUNT)
	;_GetDOSOutput("taskkill /F /PID " & $Array[1])
	ProcessClose(Int($Array[1]))
	CheckPort()
EndFunc   ;==>KillProcess

Func GUIClose()

	If @GUI_CtrlId == $closeBtn Then
		Exit
	EndIf

	If @GUI_WinHandle == $MainGui Then
		GUISetState(@SW_HIDE, $MainGui)
	EndIf
EndFunc   ;==>GUIClose


Func TrayItemTrigger()
	If @TRAY_ID == $exitTrayBtn Then
		Exit
	EndIf
EndFunc   ;==>TrayItemTrigger

;托盘点击事件
Func TrayTrigger()
	GUISetState(@SW_SHOWNORMAL)
EndFunc   ;==>TrayTrigger

;===========================================================GUI操作===========================================================
;把数组中的值显示到ListView，数组长度为3
Func _ArrayToListView($Array)
	For $i = 0 To UBound($Array) - 1
		;_ArrayDisplay($Array[1])
		;$Array[$i][0] & "|" & $Array[$i][1] &"|"& $port
		GUICtrlCreateListViewItem($Array[$i][0] & "|" & $Array[$i][1] & "|" & $Array[$i][2], $ListView)
	Next
EndFunc   ;==>_ArrayToListView

;闪烁托盘
;@param： $bool True闪烁, False取消闪烁
Func StatusFlicking($bool)
	;闪烁
	If $bool Then
		;如果图标已经在闪烁则直接退出
		If $StatusFlicking Then Return
		; 设置图标闪烁
		;TraySetIcon("shell32.dll", 200)
		TraySetState($TRAY_ICONSTATE_FLASH)
		$StatusFlicking = True
	Else ;服务正常
		;如果图标没有在闪烁则直接退出
		If Not $StatusFlicking Then Return
		;TraySetIcon("favicon.ico")
		TraySetState($TRAY_ICONSTATE_STOPFLASH)
		$StatusFlicking = False
	EndIf
EndFunc   ;==>StatusFlicking

;========================================================================服务检测=================================================
;运行服务检测程序
Func RunCheckService()
	;服务检测进程
	$CheckServicePID = Run("CheckService.exe", "", @SW_HIDE, $STDIN_CHILD + $STDOUT_CHILD)
EndFunc

;打开服务检测
Func OpenCheckService()
	If $CheckServicePID Then
		StdinWrite($CheckServicePID,1)
	EndIf
EndFunc

;关闭服务检测
Func CloseCheckService()
	If $CheckServicePID Then
		StdinWrite($CheckServicePID, 0)
	EndIf
EndFunc

;退出服务检测程序
Func ShutdownCheckService()
	If $CheckServicePID And ProcessExists($CheckServicePID) Then
		ProcessClose($CheckServicePID)
	EndIf
EndFunc

;检测服务状态并等待
Func ServiceStatusWait()
	While 1
        $sOutput = StdoutRead($CheckServicePID)
        If @error Then ; 如果进程关闭，或 StdoutRead() 返回一个错误, 则退出循环.
			MsgBox($MB_SYSTEMMODAL,$MSGBOX_TITLE,"检测服务异常,请重启检测程序")
            ExitLoop
        EndIf
		;获取到服务通知
		If @error ==0 And @extended Then
			$ServiceEnabled = Int($sOutput)
			StatusFlicking(Not $ServiceEnabled)
			If $CheckServiceSwitch Then
				If $ServiceEnabled == 0 Then
					GUICtrlSetBkColor($serviceStatusIconLabel, $COLOR_RED)
				Else
					GUICtrlSetBkColor($serviceStatusIconLabel, $COLOR_GREEN)
				EndIf
			EndIf
		EndIf
		If Not $CheckServiceSwitch Then
			GUICtrlSetBkColor($serviceStatusIconLabel, $COLOR_GRAY)
			StatusFlicking(False)
		EndIf
		Sleep(100)
    WEnd
EndFunc